package com.mybatis.boost.domain.page;

import com.mybatis.boost.domain.sort.Order;
import com.mybatis.boost.domain.sort.Sort;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;

/**
 * @author jearton
 * @since 2017/2/15
 */
@EqualsAndHashCode
public abstract class AbstractPageRequest implements Pageable {

    private final int page;
    private final int size;
    @Getter
    private final boolean pageNumberOneIndexed;
    @Getter
    private final boolean fixEdge;
    @Getter
    private final int defaultPageSize;
    @Getter
    private final int maxPageSize;

    @Getter
    @Setter
    private boolean queryCount = PageConstants.DEFAULT_QUERY_COUNT;
    @Getter
    @Setter
    private Sort sort;

    public AbstractPageRequest(int page, int size) {
        this(page, size, PageConstants.DEFAULT_PAGE_SIZE, PageConstants.MAX_PAGE_SIZE, PageConstants.DEFAULT_PAGE_NUMBER_ONE_INDEXED, PageConstants.DEFAULT_FIX_EDGE);
    }

    /**
     * Creates a new {@link AbstractPageRequest}.
     *
     * @param page                 页码
     * @param size                 每页数量
     * @param pageNumberOneIndexed 页码是否从1开始
     * @param fixEdge              是否纠正分页边界错误，比如当page<起始页时，自动设置page=起始页
     */
    public AbstractPageRequest(int page, int size, int defaultPageSize, int maxPageSize,
                               boolean pageNumberOneIndexed, boolean fixEdge, Order... orders) {
        this.defaultPageSize = defaultPageSize;
        this.maxPageSize = maxPageSize;
        this.fixEdge = fixEdge;
        this.pageNumberOneIndexed = pageNumberOneIndexed;
        if (fixEdge) {
            this.page = page < getFirstPageNumber() ? getFirstPageNumber() : page;
            this.size = size < 1 ? defaultPageSize : size > maxPageSize ? maxPageSize : size;
        } else {
            this.page = page;
            this.size = size;
        }
        if (this.page < getFirstPageNumber()) {
            throw new IllegalArgumentException("page number must not be less than " + getFirstPageNumber());
        }
        if (this.size < 1) {
            throw new IllegalArgumentException("page size must not be less than one");
        }
        if (this.size > maxPageSize) {
            throw new IllegalArgumentException("page size must not be greater than " + maxPageSize);
        }
        if (orders.length > 0) {
            this.sort = new Sort(orders);
        }
    }

    @Override
    public int getPageSize() {
        return size;
    }

    @Override
    public int getPageNumber() {
        return page;
    }
}
